﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Foxit.PDF;
using Foxit.PDF.Imaging;
using Foxit.PDF.PageElements;
using Sustainalytics.ReportGeneratorFramework.Interfaces;

namespace Sustainalytics.ReportGeneratorFramework.FrameworkEntities
{
    public class PdfDocument
    {
        #region Public Properties

        
        public PageSize PageSize { get; set; }
        public PageOrientation PageOrientation { get; set; }
        public float PageMargins { get; set; }
        public PageDimensions PageDimensions { get; set; }
        // Page Dimensions of pages
        


        public float LeftMargin { get; set; }
        public float PageMaxWidth { get; set; }
        public float PageMaxHeight { get; set; }
        public bool ShowLayoutGrid { get; set; }

        public List<PdfPage> Pages { get; set; }

        public int PageCounter
        {
            get { return _pageCounter; }
            set { _pageCounter = value; }
        }

        public Outline ParentOutline { get; set; }

        public static string AssemblyDirectory
        {
            get
            {
                var codeBase = Assembly.GetExecutingAssembly().CodeBase;
                var uri = new UriBuilder(codeBase);
                var path = Uri.UnescapeDataString(uri.Path);
                return System.IO.Path.GetDirectoryName(path);
            }
        }

        #endregion
  
        private static byte[] _companyLogoFooterImage;

        private Document _document;

        private int _pageCounter;
        private List<Page> _pages = new List<Page>();

 
        private List<IElement> docContents;

        public PdfDocument() 
        {
            // Create a _document and set it's properties
            _document = new Document
            {
                Creator = "Sustainalytics",
                Author = "Sustainalytics",
                Title = "Product Involvement Report"
            };

            PageSize = PageSize.A4;
            PageOrientation = PageOrientation.Portrait;
            PageMargins = 20f;
            PageDimensions = new PageDimensions(PageSize, PageOrientation, PageMargins);
            
            Pages = new List<PdfPage>();

            // Add the top level outline to the _document
            ParentOutline = _document.Outlines.Add("Content");
            ParentOutline.Color = new WebColor("silver");
            ParentOutline.Style = TextStyle.Bold;

            _pageCounter = 0;

            PageMaxWidth = 545;
            PageMaxHeight = 770;
            LeftMargin = 10;
            ShowLayoutGrid = false;
        }

        public void Add(IElement element)
        {
            docContents.Add(element);
        }

        public void AddRange(List<IElement> elements) 
        {
            docContents.AddRange(elements);
        }

        public void AddFooter()
        {
            //add footer for each page in the document
            var index = 1;
            foreach (var page in _document.Pages.Cast<Page>().Where(page => page != null))
            {
                if (index > 1)
                {
                    page.Elements.Add(new Line(100, 790, 520, 790, 0.5f, RgbColor.Gray));
                    page.Elements.Add(new Image(ImageData.GetImage(_companyLogoFooterImage), LeftMargin + 85f, 781, 0.24f) { Align = Align.Right, VAlign = VAlign.Top });
                }
                else
                {
                    page.Elements.Add(new Line(LeftMargin, 790, 520, 790, 0.5f, RgbColor.Gray));
                }

                page.Elements.Add(new Label(string.Format("{0} | {1}", index, _document.Pages.Count), 500, 785, 50, 10, Font.Courier, 10, TextAlign.Right, RgbColor.DimGray));

                index++;
            }
            //end add footer
        }
        public void AddPage(Page page)
        {
            _document.Pages.Add(page);
            _pageCounter++;
        }

        public void AddPages()
        {
            _pages.ForEach(p =>
            {
                _document.Pages.Add(p);
                _pageCounter++;
            });
        }

        // Render the document
        public byte[] Draw()
        {
            if(Pages.Any())
                Pages.OrderBy(p => p.PageNumber).ToList()
                     .ForEach(p => _document.Pages.Add(p));
            
            var buffer = _document.Draw();

            return buffer;
        }
        
        public PdfPage NewPage()
        {
            return new PdfPage(this);
        }

        public void AddPages(List<PdfPage> pages)
        {
            pages.ForEach(p =>
            {
                Pages.Add(p);
                PageCounter++;
                p.PageNumber = PageCounter;
            });
        }

        public Outline AddOutline(string outlineName, int pageNumber)
        {
            var outline = ParentOutline.ChildOutlines.Add(outlineName, new XYDestination(pageNumber, 0, 0));

            return outline;
        }
    }
}
